#pragma once

#include <algorithm/analytical_model/algorithm/cuda/grid/Grid.cuh>
#include <driver_types.h>

namespace solar::cuda
{
    class RectangleGrid : public Grid
    {
        public:
            __device__ __host__ RectangleGrid() = default;
            __device__ __host__ virtual ~RectangleGrid() = default;
            // Set *d_grid_helio_match_, *d_grid_helio_index_ and num_grid_helio_match_
            auto gridHelioMatch(const std::vector<RectangleHeliostat*>& heliostats) -> int override;
            auto gridHelioMatch(RectangleHeliostat* d_heliostats) -> void;
            void init() override;
            void clear() override;
            void syncCudaStream();

            inter_op::GridType type_ = inter_op::GridType::kRectangleGrid;
            int3 subgrid_num_{};        // consists of x * y * z sub-grids.
            int* d_grid_helio_match_{}; // length = num_grid_helio_match
            int* d_grid_helio_index_{}; // length = size.x * size.y * size.z + 1
            std::size_t num_grid_helio_match_{};
            cudaStream_t stream_ = nullptr;

        private:
            int* h_num_grid_helio_match_ptr_ = nullptr;
            int** h_d_grid_helio_match_ptr_ = nullptr;

            int* d_num_grid_helio_match_ptr_ = nullptr;
            int** d_d_grid_helio_match_ptr_ = nullptr;
    };
} // namespace solar::cuda
